import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:geojson/geojson.dart';
import 'package:geopoint/geopoint.dart';
import 'package:latlong/latlong.dart';
import 'package:leaflet_geo_fence_app/data_util.dart';
import 'package:leaflet_geo_fence_app/plugin/animatepolyline/animate_polyline_controller.dart';
import 'package:leaflet_geo_fence_app/plugin/animatepolyline/animate_polyline_plugin.dart';
import 'package:leaflet_geo_fence_app/plugin/userlocation/user_location_options.dart';
import 'package:leaflet_geo_fence_app/plugin/userlocation/user_location_plugin.dart';
import 'package:map_elevation/map_elevation.dart';
import 'package:pedantic/pedantic.dart';
import 'package:map_controller/map_controller.dart';
import './widgets/zoombuttons_plugin_option.dart';
import 'package:geodesy/geodesy.dart';
import 'package:flutter_map_marker_popup/flutter_map_marker_popup.dart';
import './widgets/example_popup.dart';
import './plugin/animatepolyline/animate_polyline_options.dart';
import './plugin/pathplan/path_plan_controller.dart';
import './plugin/pathplan/path_plan_plugin.dart';
import './plugin/pathplan/path_plan_options.dart';
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Leaflet Geo Fence Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  final _geo = GeoJson();
  final _geodesy = Geodesy();
  StatefulMapController _statefulMapController;
  MapController _mapController;
  StreamSubscription<StatefulMapControllerStateChange> _subscription;
  final PopupController _popupLayerController = PopupController();
  final _markerSize = 40.0;
  List<Marker> markers;
  ElevationPoint hoverPoint;
  bool _toggleStart = false;
  List<ElevationPoint> elevationPoints;
  AnimatePolylineController _animatePolylineController;
  PathPlanController _pathPlanController;
  @override
  void initState() {
    _mapController = MapController();
    _animatePolylineController = AnimatePolylineController();
    _pathPlanController = PathPlanController();
    _statefulMapController = StatefulMapController(mapController: _mapController);
    _statefulMapController.onReady.then((_) => loadData());
    _subscription = _statefulMapController.changeFeed.listen((change) => setState(() {}));
    initMarker();
    super.initState();
  }

  @override
  void dispose() {
    _subscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('CustomGeoFencePage'),actions: [IconButton(
        onPressed: () {
          _toggle();
        },
        icon: Icon(Icons.all_inclusive),
      ),IconButton(
        onPressed: () {
          _togglePath();
        },
        icon: Icon(Icons.person),
      )],),
      key: _scaffoldKey,
      body: Padding(
        padding: EdgeInsets.all(8.0),
        child: Column(
          children: [
            Padding(
              padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
              child: Text('This is a map that is showing (12.44037506700009, -69.924672003999945).'),
            ),
            Flexible(
              child: FlutterMap(
                mapController: _mapController,
                options: MapOptions(//104.057338,30.558434  //12.44037506700009, -69.924672003999945
                    center: LatLng(30.558434, 104.057338),
                    zoom: 16.0,
                    plugins: [
                      ZoomButtonsPlugin(),
                      PopupMarkerPlugin(),
                      AnimatePolylinePlugin(),
                      UserLocationPlugin(),
                      PathPlanPlugin()
                    ],
                    onTap: (LatLng point)=>_popupLayerController.hidePopup()
                ),
                layers: [
                  TileLayerOptions(
                    urlTemplate: 'http://webrd0{s}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8',
                      subdomains: ['1', '2', '3','4'],
                      tileProvider: NonCachingNetworkTileProvider()
                  ),
                  PolygonLayerOptions(polygons: _statefulMapController.polygons),
                  ZoomButtonsPluginOption(minZoom: 4, maxZoom: 19, mini: true, padding: 10, alignment: Alignment.bottomRight),
                  AnimatePolylineOptions(animatePolylineController: _animatePolylineController,polylines: DataUtil.getPolylines()),
                  MarkerLayerOptions(markers: [
                    if (hoverPoint is LatLng)
                      Marker(
                          point: hoverPoint,
                          width: 16,
                          height: 16,
                          builder: (BuildContext context) => Container(
                            decoration: BoxDecoration(
                                color: Colors.blue,
                                borderRadius: BorderRadius.circular(8)),
                          ))
                  ]),
                  UserLocationOptions(latlongChange: (LatLng latlong){
                    print('latlongChange latitude:${latlong.latitude} longitude:${latlong.longitude}');
                  }),
                  PathPlanOptions(
                    pathPlanController: _pathPlanController,
                    origin: LatLng(30.561549,104.056093),
                    destination: LatLng(30.559341,104.051587)
                  ),
                  PopupMarkerLayerOptions(
                    markers: markers,
                    popupSnap: PopupSnap.top,
                    popupController: _popupLayerController,
                    popupBuilder: (BuildContext _, Marker marker) => ExamplePopup(marker: marker),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _toggle() {

    if(!_toggleStart){
      _animatePolylineController.start();
    }else{
      _animatePolylineController.cancel();
    }
    _toggleStart = !_toggleStart;
  }
  void _togglePath() {

    if(!_toggleStart){
      _pathPlanController.start();
    }else{
      _pathPlanController.cancel();
    }
    _toggleStart = !_toggleStart;
  }
  String getSubdomain(Coords coords, TileLayerOptions options) {
    if (options.subdomains.isEmpty) {
      return '';
    }
    var index = (coords.x + coords.y).round() % options.subdomains.length;
    return options.subdomains[index];
  }

  int invertY(int y, int z) {
    return ((1 << z) - 1) - y;
  }

  void initMarker(){
    markers = DataUtil.getMarkersLatLng().map((e) => Marker(
      width: _markerSize,
      height: _markerSize,
        point:e,
      builder: (ctx) => InkWell(
        onTap: () {
//            final geoJsonPoint = GeoJsonPoint(geoPoint: GeoPoint(latitude: 12.54037506700009, longitude: -69.920672003999945));
          bool isInPolygon = false;
          _geo.multipolygons.forEach((GeoJsonMultiPolygon multiPolygon) {
            multiPolygon.polygons.forEach((polygon) {
              polygon.geoSeries.forEach((GeoSerie series) {
                if (_geodesy.isGeoPointInPolygon(e, series.toLatLng(ignoreErrors: true))) {
                  isInPolygon = true;
                }
              });
            });
          });
          if (isInPolygon) {
            _scaffoldKey.currentState.showSnackBar(SnackBar(
              content: Text('${e.latitude} ${e.longitude} is in polygon'),
            ));
          } else {
            _scaffoldKey.currentState.showSnackBar(SnackBar(
              content: Text('${e.latitude} ${e.longitude} is not in polygon'),
            ));
          }
          _popupLayerController.togglePopup(markers[0]);
        },
        child: Container(
          width: _markerSize,
          height: _markerSize,
          color: Colors.green,
          child: Icon(
            Icons.person,
            color: Colors.red,
          ),
        ),
      ),
    )).toList();
  }
  Future<void> loadData() async {
    print('Loading geojson data');
    final _data = await rootBundle.loadString('assets/polygons.geojson');
    _geo.processedMultipolygons.listen((GeoJsonMultiPolygon multiPolygon) {
      multiPolygon.polygons.forEach((polygon) {
        polygon.geoSeries.forEach((GeoSerie series) {
          _statefulMapController.addPolygon(name: polygon.name, points: series.toLatLng(), color: Colors.transparent, borderColor: Colors.green, borderWidth: 2.0);
        });
      });
      setState(() {});
    });
    final nameProperty = "ADMIN";
    unawaited(_geo.parse(_data, nameProperty: nameProperty, verbose: true));
//    unawaited(_statefulMapController.fromGeoJson(_data));
  }

}
